package com.quanyan.place.service.impl;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.quanyan.api.APIResponse;
import com.quanyan.common.Plugin.Page;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.enums.SysParameterConfigEnum;
import com.quanyan.common.utils.BeanCopierUtils;
import com.quanyan.orderpay.request.ReqWithdrawApply;
import com.quanyan.orderpay.request.WithdrawPayInfo;
import com.quanyan.orderpay.response.mq.WithdrawTransferNotify;
import com.quanyan.orderpay.service.OrderPayService;
import com.quanyan.place.constants.PlaceConstants;
import com.quanyan.place.entity.*;
import com.quanyan.place.entity.apireq.*;
import com.quanyan.place.entity.apiresp.*;
import com.quanyan.place.entity.apiresp.RespDistrict;
import com.quanyan.place.entity.base.apiresp.*;
import com.quanyan.place.mapper.*;
import com.quanyan.place.service.AdminUserService;
import com.quanyan.place.service.ApiPlaceService;
import com.quanyan.place.service.PlaceBaseService;
import com.quanyan.place.service.PlacePromoteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

import static com.quanyan.common.utils.TimeUtils.*;
import static com.quanyan.place.constants.PlaceConstants.*;

/**
 * Created by yuanxuebing on 16/12/13.
 */
@Transactional
@Service("PlacePromoteService")
public class PlacePromoteServiceImpl implements PlacePromoteService {
    private static final Logger logger = LoggerFactory.getLogger(PlacePromoteServiceImpl.class);

    @Autowired
    private TbBizPlacePromotionRewardConfigMapper placePromotionRewardConfigMapper;

    @Autowired
    private VPlacePromotionMapper vPlacePromotionMapper;

    @Autowired
    private TbBizPlacePromotionOrderMapper placePromotionOrderMapper;

    @Autowired
    private TbBizPlaceOrderMapper placeOrderMapper;

    @Autowired
    private PlaceBaseService placeBaseService;

    @Autowired
    TbBizPlaceMapper tbBizPlaceMapper;

    @Autowired
    DictMapper dictMapper;

    @Autowired
    TbCityMapper tbCityMapper;

    @Autowired
    private AdminUserService adminUserService;

    @Autowired
    private TbBizPlacePromotionRewardStatementsMapper statementsMapper;

    /*@Value("${service.promotion.bufferInMins}")
    private Integer configBufferInMins;*/

    @Value("${notify.url.rewardWithdraw}")
    private String rewardWithdrawUrl;

    @Autowired
    OrderPayService orderPayService;

    @Override
    public APIResponse getPlacePromoteOrders(ReqPromoteOrders reqVo) {
        if (reqVo == null) {
            return APIResponse.returnFail("非法的请求");
        }

        // 默认分页参数
        Integer pageNum = 0;
        Integer pageSize = 30;   // 默认每页30

        if (reqVo.getPageNum() != null) {
            pageNum = reqVo.getPageNum();
        }
        if (reqVo.getPageSize() != null) {
            pageSize = reqVo.getPageSize();
        }

        TbBizPlacePromotionOrderExample rExample = new TbBizPlacePromotionOrderExample();
        TbBizPlacePromotionOrderExample.Criteria rCriteria = rExample.createCriteria();
        if (reqVo.getPlaceId() == null) {
            return APIResponse.returnFail("只支持按场馆查询推广订单");
        }
        rCriteria.andPlaceIdEqualTo(reqVo.getPlaceId());

        if (reqVo.getPromoteStartDate() != null) {
            rCriteria.andPromotionDateGreaterThanOrEqualTo(reqVo.getPromoteStartDate());
        }

        // 注意此处是包含 todo...
        if (reqVo.getPromoteEndDate() != null) {
            rCriteria.andPromotionDateLessThanOrEqualTo(reqVo.getPromoteEndDate());
        }

        if (reqVo.getCategoryId() != null) {
            rCriteria.andCategoryIdEqualTo(reqVo.getCategoryId());
        }

        if (reqVo.getAccountNumber() != null) {
            rCriteria.andAccountNumberEqualTo(reqVo.getAccountNumber());
        }

        if (reqVo.getOrderStartDate() != null) {
            // rCriteria.andPromotionDateGreaterThanOrEqualTo(reqVo.getOrderStartDate());
        }

        // 注意此处是包含 todo...
        if (reqVo.getOrderEndDate() != null) {
            // rCriteria.andPromotionDateLessThanOrEqualTo(reqVo.getOrderEndDate());
        }

        if (reqVo.getOrderNo() != null) {
            rCriteria.andPlaceOrderIdEqualTo(reqVo.getOrderNo());
        }

        if (reqVo.getOrderStatus() != null) {
            rCriteria.andOrderStatusEqualTo(reqVo.getOrderStatus());
        } else {
            // 全部也只需要返回订单状态为 (未付款、已付款、已完成)的订单
            List<Integer> needOrderStatus = new ArrayList<>();
            needOrderStatus.add(Integer.valueOf(ORDER_PREPAY_STATUS));
            needOrderStatus.add(Integer.valueOf(ORDER_PAYED_STATUS));
            needOrderStatus.add(Integer.valueOf(ORDER_COMPLETE_PAY_STATUS));
            rCriteria.andOrderStatusIn(needOrderStatus);
        }

        if (reqVo.getUserMobile() != null) {
            rCriteria.andMobileEqualTo(reqVo.getUserMobile());
        }

        // 先获取总数
        int totalNum = placePromotionOrderMapper.countByExample(rExample);

        // 分页
        rExample.setOrderByClause("id DESC");
        Page page = new Page(pageNum * pageSize, pageSize, totalNum);
        rExample.setPage(page);
        List<TbBizPlacePromotionOrder> tbPromoteOrders = placePromotionOrderMapper.selectByExample(rExample);

        BigDecimal totalAmount = BigDecimal.valueOf(0);
        List<PromoteOrder> promoteOrders = new ArrayList<>();

        if (tbPromoteOrders != null) {
            // 计算当前页的奖励总金额
            for (TbBizPlacePromotionOrder tbPromoteOrder : tbPromoteOrders) {
                if (tbPromoteOrder != null) {
                    PromoteOrder pOrder = newPromoteOrder(tbPromoteOrder);
                    BigDecimal reward = pOrder.getRewardAmount();
                    if (reward != null) {
                        totalAmount = totalAmount.add(reward);
                    }
                    promoteOrders.add(pOrder);
                }
            }
        }

        PageObj<List<PromoteOrder>> result = PageObj.create(totalNum, pageNum, pageSize, promoteOrders);

        PromoteStatInfo statInfo = new PromoteStatInfo();
        statInfo.setTotalSMSCount(totalNum);
        statInfo.setTotalOrderCount(totalNum);
        statInfo.setTotalRewardAmount(totalAmount);
        statInfo.setTotalFinishedOrderCount(totalNum);

        RespPromoteOrders response = new RespPromoteOrders();
        response.setStatInfo(statInfo);
        response.setPromoteOrders(result);

        return APIResponse.returnSuccess(response);
    }

    @Override
    public APIResponse getPlacePromoteOrdersEx(ReqPromoteOrders reqVo) {
        if (reqVo == null) {
            return APIResponse.returnFail("非法的请求");
        }

        // 默认分页参数
        Integer pageNum = 0;
        Integer pageSize = 30;   // 默认每页30

        if (reqVo.getPageNum() == null) {
            reqVo.setPageNum(pageNum);
        }
        if (reqVo.getPageSize() == null) {
            reqVo.setPageSize(pageSize);
        }
        if (reqVo.getUserMobile()!=null){
            reqVo.setUserMobile("%"+reqVo.getUserMobile().trim()+"%");
        }
        if (reqVo.getAccountNumber()!=null){
            reqVo.setAccountNumber("%"+reqVo.getAccountNumber().trim()+"%");
        }
        if (reqVo.getOrderNo()!=null){
            reqVo.setOrderNo("%"+reqVo.getOrderNo().trim()+"%");
        }

        // 获取分页总数
        PromoteStatInfo statInfo = vPlacePromotionMapper.getPlacePromoteStat(reqVo);
        Page page = new Page(reqVo.getPageNum() * reqVo.getPageSize(), reqVo.getPageSize(), statInfo.getTotalRecordCount());
        reqVo.setPage(page);
        List<PromoteOrder> promoteOrders = vPlacePromotionMapper.getPlacePromoteOrders(reqVo);
        TbBizPlace place=placeBaseService.getPlaceById(reqVo.getPlaceId());
        PageObj<List<PromoteOrder>> result = PageObj.create(statInfo.getTotalRecordCount(), reqVo.getPageNum(), reqVo.getPageSize(), promoteOrders);

        RespPromoteOrders response = new RespPromoteOrders();
        response.setBusinessMode(place!=null?(int)place.getBusinessMode():null);
        response.setStatInfo(statInfo);
        response.setPromoteOrders(result);

        return APIResponse.returnSuccess(response);
    }

    @Override
    public APIResponse getPlacePromotionByAdmin(ReqPromotionByAdmin reqVo) {
        if (reqVo == null) {
            return APIResponse.returnFail("非法的请求");
        }

        // 默认分页参数
        Integer pageNum = 0;
        Integer pageSize = 30;   // 默认每页30

        if (reqVo.getPageNum() == null) {
            reqVo.setPageNum(pageNum);
        }
        if (reqVo.getPageSize() == null) {
            reqVo.setPageSize(pageSize);
        }

        // 模糊查询字段
        if (reqVo.getUserMobile()!=null){
            reqVo.setUserMobile("%"+reqVo.getUserMobile().trim()+"%");
        }
        if (reqVo.getAccountNumber()!=null){
            reqVo.setAccountNumber("%"+reqVo.getAccountNumber().trim()+"%");
        }
        if (reqVo.getOrderNo()!=null){
            reqVo.setOrderNo("%"+reqVo.getOrderNo().trim()+"%");
        }
        if (reqVo.getPlaceNo()!=null){
            reqVo.setPlaceNo("%"+reqVo.getPlaceNo().trim()+"%");
        }
        if (reqVo.getPlaceName()!=null){
            reqVo.setPlaceName("%"+reqVo.getPlaceName().trim()+"%");
        }

        // 获取分页总数
        PromoteStatInfo statInfo = vPlacePromotionMapper.getPlacePromotionStat(reqVo);
        Page page = new Page(reqVo.getPageNum() * reqVo.getPageSize(), reqVo.getPageSize(), statInfo.getTotalRecordCount());
        reqVo.setPage(page);
        List<PromoteResultInfo> promoteResults = vPlacePromotionMapper.getPlacePromotion(reqVo);

        // 将cityId -> cityName,前端做还是后端做
        PageObj<List<PromoteResultInfo>> result = PageObj.create(statInfo.getTotalRecordCount(), reqVo.getPageNum(), reqVo.getPageSize(), promoteResults);

        RespPromotionByAdmin response = new RespPromotionByAdmin();
        response.setStatInfo(statInfo);
        response.setPromoteResults(result);

        return APIResponse.returnSuccess(response);
    }

    @Override
    public APIResponse getPromoteRewards(ReqPromoteRewards reqVo) {
        if (reqVo == null) {
            return APIResponse.returnFail("非法的请求");
        }

        // 默认分页参数
        Integer pageNum = 0;
        Integer pageSize = 30;   // 默认每页30

        if (reqVo.getPageNum() == null) {
            reqVo.setPageNum(pageNum);
        }
        if (reqVo.getPageSize() == null) {
            reqVo.setPageSize(pageSize);
        }

        // 以下字段是模糊查询
        if (reqVo.getUserMobile() != null && !reqVo.getUserMobile().isEmpty()){
            reqVo.setUserMobile("%" + reqVo.getUserMobile().trim() + "%");
        } else {
            reqVo.setUserMobile(null);
        }

        if (reqVo.getOrderNo() != null && !reqVo.getOrderNo().isEmpty()){
            reqVo.setOrderNo("%" + reqVo.getOrderNo().trim() + "%");
        } else {
            reqVo.setOrderNo(null);
        }

        // 获取分页总数
        PromoteRewardStatInfo statInfo = vPlacePromotionMapper.getPromoteRewardStat(reqVo);
        Page page = new Page(reqVo.getPageNum() * reqVo.getPageSize(), reqVo.getPageSize(), statInfo.getTotalRecordCount());
        reqVo.setPage(page);
        List<PromoteReward> promoteRewards = vPlacePromotionMapper.getPromoteRewards(reqVo);
        PageObj<List<PromoteReward>> result = PageObj.create(statInfo.getTotalRecordCount(), reqVo.getPageNum(), reqVo.getPageSize(), promoteRewards);

        RespPromoteRewards response = new RespPromoteRewards();
        response.setStatInfo(statInfo);
        response.setPromoteOrders(result);

        return APIResponse.returnSuccess(response);
    }

    @Override
    public APIResponse getPromoteWithdrawals(ReqPromoteWithdrawals reqVo) {
        if (reqVo == null) {
            return APIResponse.returnFail("非法的请求");
        }

        // 默认分页参数
        Integer pageNum = 0;
        Integer pageSize = 30;   // 默认每页30

        if (reqVo.getPageNum() == null) {
            reqVo.setPageNum(pageNum);
        }
        if (reqVo.getPageSize() == null) {
            reqVo.setPageSize(pageSize);
        }

        // 以下字段是模糊查询
        if (reqVo.getStatementNo()!=null && !reqVo.getStatementNo().isEmpty()){
            reqVo.setStatementNo("%"+reqVo.getStatementNo().trim()+"%");
        } else {
            reqVo.setStatementNo(null);
        }

        // 获取分页总数
        PromoteWithdrawalsStatInfo statInfo = vPlacePromotionMapper.getPromoteWithdrawalsStatInfo(reqVo);
        Page page = new Page(reqVo.getPageNum() * reqVo.getPageSize(), reqVo.getPageSize(), statInfo.getTotalRecordCount());
        reqVo.setPage(page);
        List<PromoteWithdrawals> promoteWithdrawals = vPlacePromotionMapper.getPromoteWithdrawals(reqVo);
        PageObj<List<PromoteWithdrawals>> result = PageObj.create(statInfo.getTotalRecordCount(), reqVo.getPageNum(), reqVo.getPageSize(), promoteWithdrawals);

        RespPromoteWithdrawals response = new RespPromoteWithdrawals();
        response.setStatInfo(statInfo);
        response.setPromoteWithdrawals(result);

        return APIResponse.returnSuccess(response);
    }

    @Override
    public APIResponse getPromoteReconciliation(ReqPromoteReconciliation reqVo) {
        if (reqVo == null) {
            return APIResponse.returnFail("非法的请求");
        }

        // 默认分页参数
        Integer pageNum = 0;
        Integer pageSize = 30;   // 默认每页30

        if (reqVo.getPageNum() == null) {
            reqVo.setPageNum(pageNum);
        }
        if (reqVo.getPageSize() == null) {
            reqVo.setPageSize(pageSize);
        }

        if (reqVo.getStartDate()!=null&&!reqVo.getStartDate().isEmpty()){
            reqVo.setStartDate(reqVo.getStartDate()+"-03");//代码上的处理，与业务逻辑无关
        }else{
            reqVo.setStartDate(null);
        }
        if (reqVo.getEndDate()!=null&&!reqVo.getEndDate().isEmpty()){
            reqVo.setEndDate(reqVo.getEndDate()+"-03");//代码上的处理，与业务逻辑无关
        }else{
            reqVo.setEndDate(null);
        }

        // 以下字段是模糊查询
        if (reqVo.getPlaceName()!=null && !reqVo.getPlaceName().isEmpty()){
            reqVo.setPlaceName("%"+reqVo.getPlaceName().trim()+"%");
        } else {
            reqVo.setPlaceName(null);
        }

        if (reqVo.getPlaceCode()!=null && !reqVo.getPlaceCode().isEmpty()){
            reqVo.setPlaceCode("%"+reqVo.getPlaceCode().trim()+"%");
        } else {
            reqVo.setPlaceCode(null);
        }

        if (reqVo.getAdminMobile()!=null && !reqVo.getAdminMobile().isEmpty()){
            reqVo.setAdminMobile("%"+reqVo.getAdminMobile().trim()+"%");
        } else {
            reqVo.setAdminMobile(null);
        }

        if (reqVo.getAdminName()!=null && !reqVo.getAdminName().isEmpty()){
            reqVo.setAdminName("%"+reqVo.getAdminName().trim()+"%");
        } else {
            reqVo.setAdminName(null);
        }

        // 应付金额：对方已结算且我方未付款的金额，不论是否申请提现，仅在不筛选日期时显示
        boolean needShouldAmount = false;
        if (reqVo.getStartDate() == null && reqVo.getEndDate() == null) {
            needShouldAmount = true;
        }

        PromoteReconciliationStatInfo statInfo = new PromoteReconciliationStatInfo();
        Integer totalRecordCount = 0;                             // 总记录数
        BigDecimal totalRewardAmount =  BigDecimal.valueOf(0);    // 总金额
        BigDecimal totalPersonalTax =  BigDecimal.valueOf(0);
        BigDecimal totalAfterTaxIncome =  BigDecimal.valueOf(0);
        BigDecimal payedRewardAmount =  BigDecimal.valueOf(0);    // 已付
        BigDecimal shouldRewardAmount =  BigDecimal.valueOf(0);   // 应付

        // 所有的记录
        List<PromoteReconciliation> promoteReconciliations = new ArrayList<>();

        // 获取所有候选的推广人列表
        List<ReconciliationCandidate> candidates = vPlacePromotionMapper.getReconciliationCandidates(reqVo);
        if (candidates != null && candidates.size() > 0) {
            totalRecordCount = candidates.size();

            List<Integer> uids = new ArrayList<>();
            for (ReconciliationCandidate candidate: candidates) {
                uids.add(candidate.getAdminId());
            }

            Map<String, PromoteReconciliation> reconMap = new HashMap<>();
           /* List<PromoteReconciliation> recons1 = vPlacePromotionMapper.getRewardReconciliation(uids, reqVo.getStartDate(), reqVo.getEndDate());
            if (recons1 != null && recons1.size() > 0) {
                for (PromoteReconciliation recon : recons1) {
                    reconMap.put(String.format("R-%d", recon.getAdminId()), recon);
                }
            }*/

            List<PromoteReconciliation> recons2 = vPlacePromotionMapper.getStatmentReconciliation(uids, reqVo.getStartDate(), reqVo.getEndDate());
            if (recons2 != null && recons2.size() > 0) {
                for (PromoteReconciliation recon : recons2) {
                    reconMap.put(String.format("S-%d", recon.getAdminId()), recon);
                }
            }

            for (ReconciliationCandidate candidate: candidates) {
                PromoteReconciliation recon = new PromoteReconciliation();
                //PromoteReconciliation recon1 = reconMap.get(String.format("R-%d", candidate.getAdminId()));
                PromoteReconciliation recon2 = reconMap.get(String.format("S-%d", candidate.getAdminId()));

                recon.setCity(candidate.getCity());
                recon.setAdminId(candidate.getAdminId());
                recon.setAdminName(candidate.getAdminName());
                recon.setAdminMobile(candidate.getAdminMobile());
                recon.setPlaceId(candidate.getPlaceId());
                recon.setPlaceName(candidate.getPlaceName());
                recon.setPlaceCode(candidate.getPlaceCode());

                if (recon2 != null) {
                    recon.setSumRewardAmount(recon2.getSumRewardAmount());//结算佣金(税前收入)
                    recon.setSumPersonalTax(recon2.getSumPersonalTax());
                    recon.setSumAfterTaxIncome(recon2.getSumAfterTaxIncome());
                } else {
                    recon.setSumRewardAmount(BigDecimal.valueOf(0));
                    recon.setSumPersonalTax(BigDecimal.valueOf(0));
                    recon.setSumAfterTaxIncome(BigDecimal.valueOf(0));
                }
                totalRewardAmount = totalRewardAmount.add(recon.getSumRewardAmount());//总结算佣金
                totalPersonalTax = totalPersonalTax.add(recon.getSumPersonalTax()!=null?recon.getSumPersonalTax():BigDecimal.valueOf(0));//总应扣个税
                totalAfterTaxIncome = totalAfterTaxIncome.add(recon.getSumAfterTaxIncome()!=null?recon.getSumAfterTaxIncome():BigDecimal.valueOf(0));//总税后收入

                if (recon2 != null) {
                    recon.setPayedRewardAmount(recon2.getPayedRewardAmount());//已付金额
                } else {
                    recon.setPayedRewardAmount(BigDecimal.valueOf(0));
                }
                payedRewardAmount = payedRewardAmount.add(recon.getPayedRewardAmount());//总已付金额
                // 处理应付
                //if (needShouldAmount) {
                    recon.setShouldRewardAmount(recon.getSumAfterTaxIncome().subtract(recon.getPayedRewardAmount()));//应付金额
                    shouldRewardAmount = shouldRewardAmount.add(recon.getShouldRewardAmount());//总应付金额
               // } else {
                 //   recon.setShouldRewardAmount(null);
                //}

                promoteReconciliations.add(recon);
            }
        }

        if (totalRecordCount != promoteReconciliations.size()) {
            return APIResponse.returnFail("数据条数不一致");
        }

        statInfo.setTotalRecordCount(totalRecordCount);
        statInfo.setTotalRewardAmount(totalRewardAmount);//总结算佣金
        statInfo.setPayedRewardAmount(payedRewardAmount);//总已付金额
        statInfo.setTotalPersonalTax(totalPersonalTax);//总应扣个税
        statInfo.setTotalAfterTaxIncome(totalAfterTaxIncome);//税后收入
       // if (needShouldAmount) {
            statInfo.setShouldRewardAmount(shouldRewardAmount);//总已付金额
       // } else {
          //  statInfo.setShouldRewardAmount(BigDecimal.ZERO);
       // }

        RespPromoteReconciliation response = new RespPromoteReconciliation();
        response.setStatInfo(statInfo);

        if (totalRecordCount > 0) {
            // 需要slice
            int begin = reqVo.getPageNum() * reqVo.getPageSize();
            if (begin < 0 || begin >= totalRecordCount) {
                return APIResponse.returnFail("分页起始错误");
            }
            int end = reqVo.getPageNum() * reqVo.getPageSize() + reqVo.getPageSize();
            if (end >= totalRecordCount) {
                end = totalRecordCount;
            }

            PageObj<List<PromoteReconciliation>> result =
                    PageObj.create(statInfo.getTotalRecordCount(),
                            reqVo.getPageNum(),
                            reqVo.getPageSize(),
                            promoteReconciliations.subList(begin, end));

            response.setPromoteReconciliations(result);
        }

        return APIResponse.returnSuccess(response);
    }

    @Override
    public void promoteSettleTask() {
        // 选出所有还有未结算推广单的场馆
        List<Integer> placeIds = vPlacePromotionMapper.selectDistinctPlaceIds();
        if (placeIds == null || placeIds.size() <= 0) {
            logger.info("没有未结算推广单的场馆,本次结算完成.");
            return;
        }

        // 查询奖励配置
        Map<Integer, Map<String, TbBizPlacePromotionRewardConfig>> placeConfigMap = getRewardConfigs(placeIds);
        if (placeConfigMap == null || placeConfigMap.size() != placeIds.size()) {
            logger.warn("无法获取某些场馆的奖励配置,请检查推广奖励配置表!!! ");
            return;
        }

        // 消费时间 > (当前时间 - buffer时间段)
        int bufferInMins = 60;  // 分钟为单位的buffer时间段
        Integer configBufferInMins=60;
        /*  if (configBufferInMins != null) {
            bufferInMins = this.configBufferInMins;
        }*/
        Date now = new Date();
        Date minConsumeTime = getDateAfterMinutes(now, -1 * bufferInMins);

        // 场馆id随机乱序一下,否则会不公平,因为推广次数是递增的,先结算意味着订单的推广次数偏小,该场馆的推广者获得奖励偏多。
        Collections.shuffle(placeIds);
        for (Integer placeId : placeIds) {
            if (placeId > 0) {
                Map<String, TbBizPlacePromotionRewardConfig> placeConfig = placeConfigMap.get(placeId);
                if (placeConfig == null) {
                    logger.error("无法获取场馆{}的奖励配置!!! ", placeId);
                    continue;
                }
                settlePlacePromotion(placeId, now, minConsumeTime, placeConfig);
            }
        }
    }

    public PromoteOrder newPromoteOrder(TbBizPlacePromotionOrder tbPPO) {
        PromoteOrder po = new PromoteOrder();

        BeanCopierUtils.copyProperties(tbPPO, po);

        return po;
    }

    // 获取奖励配置
    Map<Integer, Map<String, TbBizPlacePromotionRewardConfig>> getRewardConfigs(List<Integer> placeIds) {
        Map<Integer, Map<String, TbBizPlacePromotionRewardConfig>> placeConfigMap = new HashMap<>();

        // 先查默认值
        TbBizPlacePromotionRewardConfigExample example1 = new TbBizPlacePromotionRewardConfigExample();
        TbBizPlacePromotionRewardConfigExample.Criteria criteria1 = example1.createCriteria();
        criteria1.andPlaceIdEqualTo(-1);
        List<TbBizPlacePromotionRewardConfig> defaultConfigs = placePromotionRewardConfigMapper.selectByExample(example1);
        if (defaultConfigs == null || defaultConfigs.size() <=0 ) {
            logger.warn("推广奖励金,没有配置默认奖励金额!!!");
        }

        TbBizPlacePromotionRewardConfigExample example2 = new TbBizPlacePromotionRewardConfigExample();
        TbBizPlacePromotionRewardConfigExample.Criteria criteria2 = example2.createCriteria();
        criteria2.andPlaceIdIn(placeIds);
        List<TbBizPlacePromotionRewardConfig> configs = placePromotionRewardConfigMapper.selectByExample(example2);


        for (Integer placeId : placeIds) {
            List<TbBizPlacePromotionRewardConfig> placeConfigs = new ArrayList<>();

            if (defaultConfigs != null) {
                placeConfigs.addAll(defaultConfigs);
            }

            if (configs != null) {
                for (TbBizPlacePromotionRewardConfig config : configs) {
                    if (config != null && config.getPlaceId() == placeId) {
                        placeConfigs.add(config);
                    }
                }
            }

            // 如果有默认值其会在最前,因此顺序遍历的话,后面的配置可覆盖默认值.
            Map<String, TbBizPlacePromotionRewardConfig> configMap = new HashMap<>();
            for (TbBizPlacePromotionRewardConfig config : placeConfigs) {
                String key = createConfigKey(config.getCategoryId(), config.getTimes());
                configMap.put(key, config);
            }

            if (configMap.size() > 0) {
                placeConfigMap.put(placeId, configMap);
            }
        }

        return placeConfigMap;
    }

    List<TbBizPlacePromotionOrder> listUnsettleOrder(Integer placeId, Date consumeTime) {
        TbBizPlacePromotionOrderExample rExample = new TbBizPlacePromotionOrderExample();
        TbBizPlacePromotionOrderExample.Criteria rCriteria = rExample.createCriteria();
        if (placeId != null) {
            rCriteria.andPlaceIdEqualTo(placeId);
        }
       /* if (consumeTime != null) {
            rCriteria.andConsumeDateGreaterThanOrEqualTo(consumeTime);
        }*/
        rCriteria.andSettleStatusEqualTo((byte) 0);
        rExample.setOrderByClause("consume_date DESC");

        return placePromotionOrderMapper.selectByExample(rExample);
    }

    //
    public void settlePlacePromotion(Integer placeId, Date settleTime, Date minConsumeTime,
                                     Map<String, TbBizPlacePromotionRewardConfig> configs) {
        logger.debug("开始执行场馆推广奖励结算");

        // 先选出本批次待处理订单:取出 消费时间 >= 当前时间 - buffer时间段 且 结算状态未关闭的订单
        List<TbBizPlacePromotionOrder> orders = listUnsettleOrder(placeId, minConsumeTime);
        if (orders == null || orders.size() <= 0) {
            return;
        }

        Map<String, TbBizPlacePromotionOrder> orderMap = new HashMap<>();
        List<String> orderNos = new ArrayList<>();
        for (TbBizPlacePromotionOrder order : orders) {
            orderNos.add(order.getPlaceOrderId());
            orderMap.put(order.getPlaceOrderId(), order);
        }

        // 批量获取订单最新状态
        TbBizPlaceOrderExample example = new TbBizPlaceOrderExample();
        TbBizPlaceOrderExample.Criteria criteria = example.createCriteria();
        criteria.andPlaceIdEqualTo(placeId);
        criteria.andPlaceOrderIdIn(orderNos);
        List<TbBizPlaceOrder> tbOrders = placeOrderMapper.selectByExample(example);
        if (tbOrders == null || tbOrders.size() <= 0) {
            return;
        }

        // 一单单结算,最后再同步到数据库中
        List<TbBizPlacePromotionOrder> needUpdateOrders = new ArrayList<>();
        for (TbBizPlaceOrder tbOrder : tbOrders) {
            TbBizPlacePromotionOrder thizPOrder = orderMap.get(tbOrder.getPlaceOrderId());
            boolean needUpdate = settlePromotionOrder(tbOrder, thizPOrder, configs, settleTime);
            if (needUpdate) {
                needUpdateOrders.add(thizPOrder);
                // 更新数据库
                thizPOrder.setUpdateTime(new Date());
                placePromotionOrderMapper.updateByPrimaryKeySelective(thizPOrder);
            }
        }

        return;
    }

    // 是否需要更新到数据库
    public boolean settlePromotionOrder(TbBizPlaceOrder tbOrder, TbBizPlacePromotionOrder pOrder,
                                    Map<String, TbBizPlacePromotionRewardConfig> configs,
                                    Date settleTime) {
        boolean needUpdate = false;

        // 订单状态是否改变
        if (!tbOrder.getOrderStatus().equals(pOrder.getOrderStatus())) {
            // 更新订单状态
            pOrder.setOrderStatus(Integer.valueOf(tbOrder.getOrderStatus()));

            // 对于状态变为"已完成"的订单
            if (ORDER_COMPLETE_PAY_STATUS.equals(tbOrder.getOrderStatus())) {
                // 确定是否奖励及奖励金额
                Integer promotionTimes = vPlacePromotionMapper.increasePromotionTimes(pOrder.getMobile());

                String key = createConfigKey(tbOrder.getCategoryId(), promotionTimes);
                TbBizPlacePromotionRewardConfig config = configs.get(key);
                if (config != null) {
                    pOrder.setRewardAmount(config.getAmount());
                } else {
                    //pOrder.setRewardAmount(BigDecimal.valueOf(0));
                }

                pOrder.setPromotionCount(promotionTimes);
            }

            needUpdate = true;
        }

        // 是否需要关闭结算
        boolean needClose = false;
        if (ORDER_COMPLETE_PAY_STATUS.equals(tbOrder.getOrderStatus()) ||
                ORDER_REFUND_STATUS.equals(tbOrder.getOrderStatus()) ||
                ORDER_CLOSE_STATUS.equals(tbOrder.getOrderStatus())) {
            needClose = true;
        }

        // 时间上"超时"的订单也要关闭结算
        /*if (pOrder.getConsumeDate().before(settleTime)) {
            needClose = true;
        }*/

        if (needClose) {
            pOrder.setSettleStatus((byte) 1);
            needUpdate = true;
        }

        return needUpdate;
    }


    public String createConfigKey(Integer cateId, Integer times) {
        return String.format("%d-%d", cateId, times);
    }


    @Override
    public void promoteRewardSettleTask() throws Exception {
        // 按场馆-推广人来逐个结算
        Date now = new Date();

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        calendar.set(year, month, 1, 0, 0, 0);
        Date endTime = getDateAfterSeconds(calendar.getTime(), -1);
        Date startTime = getDateAfterMonth(endTime, -12);   // 只取最近一年的订单

        List<PromoteRewardSettleCandidate> candidates = vPlacePromotionMapper.getRewardCandidates(startTime, endTime);
        if (candidates == null || candidates.size() <= 0) {
            logger.info("没有待奖励的候选者,本次结算完成.");
            return;
        }

        for (PromoteRewardSettleCandidate candidate : candidates) {
            candidate.setSettleStartTime(startTime);
            candidate.setSettleEndTime(endTime);

            // 早前tb_biz_place_promotion_record中没有记录uid,所以可能存在uid为空的情况
            if (candidate.getPlaceId() == null ||  candidate.getAdminId() == null) {
                logger.warn("无法获取从记录表中获取场馆id或管理员uid,跳过该候选{}", candidate);
                continue;
            }

            try {
                settlePromotionReward(candidate);
            } catch (Exception e) {
                e.printStackTrace();
                throw e;
            }
        }
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void settlePromotionReward(PromoteRewardSettleCandidate candidate) throws Exception {
        Integer placeId = candidate.getPlaceId();
        Integer adminId = candidate.getAdminId();

        RespBizPlaceBaseInfo baseInfo = placeBaseInfoLite(placeId);
        if (baseInfo == null) {
            logger.warn("无法获取场馆placeId:{}的基本信息", placeId);
            return;
        }

        TbAdminUser adminUser = adminUserService.getAdminUser(adminId);
        if (adminUser == null) {
            logger.warn("无法获取管理员adminId:{}的基本信息", adminId);
            return;
        }

        // 获取结算期内可获佣金的订单
        List<PromoteOrder> orders = new ArrayList<>();
        try {
            orders = vPlacePromotionMapper.getRewardPromoteOrders(candidate);
        } catch (Exception ex) {
            logger.error("获取可奖励佣金的订单集合异常:{}", ex);
            return;
        }

         if (orders == null || orders.size() <= 0) {
            logger.info("{}奖励订单为空", candidate);
            return;
        }

        // 确定佣金计算 起-止 日期
        Date earliestRewardDate = new Date();
        BigDecimal totalAmount =  BigDecimal.valueOf(0);
        BigDecimal thresholdAmount =  BigDecimal.valueOf(50);
        for (PromoteOrder order : orders) {
            int i = order.getRewardAmount().compareTo(BigDecimal.ZERO);
            if (i == 1) {  // > 0
                totalAmount = totalAmount.add(order.getRewardAmount());
            }
            if (order.getPromotionDate() != null &&
                    earliestRewardDate.after(order.getConsumeDate())) {
                earliestRewardDate = order.getConsumeDate();
            }
        }

        // 如果不到50积累到下一期,直接跳出
       /* if (totalAmount.compareTo(thresholdAmount) < 0) {
            logger.info("{}本次奖励金额:{} < {},积累到下次结算", adminId, totalAmount, thresholdAmount);
            return;
        }*/

        // 用户账号信息不存在
        if (adminUser.getBcId() == null ||
                adminUser.getBcBank() == null ||
                adminUser.getBcCardno() == null) {
            logger.warn("无法获取管理员的账户信息:{}", adminUser);
            return;
        }

        // 插入结算单
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(earliestRewardDate);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        calendar.set(year, month, 1, 0, 0, 0);
        Date realSettleStartTime = calendar.getTime();
        candidate.setSettleStartTime(realSettleStartTime);

        TbBizPlacePromotionRewardStatements statement =
                addRewardStatement(baseInfo, adminUser, candidate, totalAmount);

        // 提现结算明细
        vPlacePromotionMapper.insertRewardStatementDetails(statement.getId(), orders);

        // 修改推广订单中 提现结算状态
        vPlacePromotionMapper.batchUpdateOrderRewardSettleStatus(orders, 1);

        // 将结算单post给财务系统,异步处理
        int ret = applyRewardWithdraw(adminUser, statement);
        if (ret != 0) {
            throw new RuntimeException("通知转账失败");
        }

        // 如果post成功将结算单状态设置为打款中
        statement.setStatementStatus((byte) 2);
        statementsMapper.updateByPrimaryKey(statement);
    }

    TbBizPlacePromotionRewardStatements addRewardStatement(RespBizPlaceBaseInfo baseInfo,
                               TbAdminUser user,
                               PromoteRewardSettleCandidate candidate,
                               BigDecimal totalAmount) {
        // 生成提现流水号
        String statementNo = generateStatementNo(user.getId());
        TbBizPlacePromotionRewardStatements statement = new TbBizPlacePromotionRewardStatements();

        statement.setStatementNo(statementNo);
        statement.setPlaceId(baseInfo.getId());
        statement.setPlaceName(baseInfo.getName());
        statement.setCityId(baseInfo.getCityObj().getId());
        statement.setCity(baseInfo.getCityObj().getName());
        statement.setAccountNumber(user.getTrueName());
        statement.setUid(user.getId());
        statement.setAdminMobile(user.getMobile());
        statement.setStatementStartDate(candidate.getSettleStartTime());
        statement.setStatementEndDate(candidate.getSettleEndTime());
        statement.setRewardAmount(totalAmount);//税前收入
        statement.setStatementStatus((byte) 1);
        statement.setCreateDate(new Date());

        BigDecimal base=new BigDecimal(4000);
        BigDecimal personalTax=new BigDecimal(0);//应扣个税
        BigDecimal afteTaxIncome=new BigDecimal(0);//税后收入

        int value=totalAmount.compareTo(base);
        //税前佣金收入大于4000 应扣个税 = 税前佣金收入 x 0.8 x  0.2 ;税前佣金收入小于等于4000，应扣个税=（税前佣金收入-800）x 0.2 。
        if (value==1){
            personalTax=totalAmount.multiply(new BigDecimal(0.16)).setScale(2,BigDecimal.ROUND_HALF_UP);
        }else{
            personalTax=totalAmount.subtract(new BigDecimal(800)).multiply(new BigDecimal(0.2)).setScale(2,BigDecimal.ROUND_HALF_UP);
            if (personalTax.compareTo(BigDecimal.ZERO)==-1){
                personalTax=BigDecimal.valueOf(0);
            };


        }
        afteTaxIncome=totalAmount.subtract(personalTax).setScale(2,BigDecimal.ROUND_HALF_UP);
        statement.setPersonalTax(personalTax);
        statement.setAfterTaxIncome(afteTaxIncome);


        statementsMapper.insertSelective(statement);
        return statement;
    }

    // 前台管理员ID+时间戳
    String generateStatementNo(Integer adminId) {
        long now = System.currentTimeMillis();
        return String.format("%4d-%d", adminId, now) ;
    }

    // 通知财务打款
    int applyRewardWithdraw(TbAdminUser user, TbBizPlacePromotionRewardStatements statement) {
        ReqWithdrawApply reqWithdrawApply = new ReqWithdrawApply();
        reqWithdrawApply.setSourceSystemCode(Constants.PLACE_SYSTEM_CODE);
        reqWithdrawApply.setSourceBusinessCode(PlaceConstants.PLACE_PROMOTE_EXTRACT_CODE);
        reqWithdrawApply.setPayType(user.getBcId());

        WithdrawPayInfo payInfo = new WithdrawPayInfo();

        payInfo.setApplyNo(statement.getStatementNo());
        payInfo.setAccountNo(user.getBcCardno());
        payInfo.setName(user.getBcAccountName());
        payInfo.setPhone(user.getMobile());
        payInfo.setBalance(BigDecimal.valueOf(0));
        payInfo.setAmount(statement.getAfterTaxIncome());
        payInfo.setBusinessId(user.getId());
        payInfo.setApplyTime(new Date());
        String desc = String.format("%s-%s短信推广佣金",
                getSimpleDateEngString(statement.getStatementStartDate()),
                getSimpleDateEngString(statement.getStatementEndDate()));
        payInfo.setWithdrawDesc(desc);

        reqWithdrawApply.setWithdrawPayInfo(payInfo);
        reqWithdrawApply.setNotifyUrl(rewardWithdrawUrl);

        logger.info("orderPayService.applyWithdraw--->"+ JSON.toJSONString(reqWithdrawApply));
        APIResponse<String> respPreOrderAPIResponse = orderPayService.applyWithdraw(reqWithdrawApply);
        if (!respPreOrderAPIResponse.isRet()) {
            logger.warn("orderPayService.applyWithdraw response:{}", respPreOrderAPIResponse);
            return -1;
        }

        return 0;
    }


    @Override
    public APIResponse promoteRewardPayCallback(WithdrawTransferNotify notify) {
        if (notify == null) {
            return APIResponse.returnFail("无效的notify对象");
        }

        // 更新
        Boolean tag = notify.getTag();
        if (tag != null && tag) {
            String No = notify.getApplyNo();
            logger.info("promoteRewardPayCallback tag:{} No:{} notify:{}", tag, No, notify);

            if (No != null && !No.isEmpty()) {
                TbBizPlacePromotionRewardStatementsExample example = new TbBizPlacePromotionRewardStatementsExample();
                TbBizPlacePromotionRewardStatementsExample.Criteria rCriteria = example.createCriteria();
                rCriteria.andStatementNoEqualTo(No);

                TbBizPlacePromotionRewardStatements record = new TbBizPlacePromotionRewardStatements();
                record.setTransferDate(new Date());
                record.setStatementStatus((byte) 3);

                statementsMapper.updateByExampleSelective(record, example);
            }
        }

        return APIResponse.returnSuccess("RewardPay回调成功");
    }


    public RespBizPlaceBaseInfo placeBaseInfoLite(Integer placeId) {
        RespBizPlaceBaseInfo respBizPlaceBaseInfo = new RespBizPlaceBaseInfo();

        //获取场馆基本信息
        TbBizPlace tbBizPlace = tbBizPlaceMapper.selectByPrimaryKey(placeId);
        if (tbBizPlace == null) {
            return null;
        }

        //获取场馆城市信息
        TbCity tbCity = tbCityMapper.selectByPrimaryKey(tbBizPlace.getCityId());
        if (tbCity == null) {
            return null;
        }

        RespCity cityInfo = new RespCity();
        cityInfo.setId(tbCity.getId());
        cityInfo.setName(tbCity.getName());

        respBizPlaceBaseInfo.setId(tbBizPlace.getId());
        respBizPlaceBaseInfo.setName(tbBizPlace.getName());
        respBizPlaceBaseInfo.setCityObj(cityInfo);

        return respBizPlaceBaseInfo;
    }
}
